package cn.ycq.im.commons.config;

import cn.ycq.im.commons.annotation.Router;
import cn.ycq.im.commons.exceptions.GlobalExceptionHandlers;
import cn.ycq.im.controller.UserController;
import cn.ycq.im.http.Routers;
import io.netty.handler.codec.http.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

@Slf4j
@Component
public class ControllerInitializer implements BeanPostProcessor {

    @Value("${server.baseUrl}")
    private String baseUrl;


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Class<?> aClass = bean.getClass();
        if (aClass.isAnnotationPresent(Controller.class)) {
            log.info("Controllers.postProcessBeforeInitialization::{}", aClass.getName());
            buildRouterMethod(aClass, bean);
        }

        return bean;
    }

    private void buildRouterMethod(Class<?> controllerClass, Object controller) {
        Method[] methods = controllerClass.getMethods();
        for (Method method : methods) {
            if (!Modifier.isPublic(method.getModifiers())
                    && !Modifier.isStatic(method.getModifiers())) {
                log.info("method {} is not public of is static！", method.getName());
                continue;
            }
            if (method.isAnnotationPresent(Router.class)) {
                Router router = method.getAnnotation(Router.class);
                String m = router.method();

                String uri = baseUrl+router.uri();
                uri = uri.replaceAll("/+","/");
                HttpMethod httpMethod = methodStringToHttpMethod(m);

                Routers.DEFAULT.register(httpMethod,   uri, (req, res) -> {
                    try {
                        method.invoke(controller, req, res);
                    } catch (Exception e) {
                        GlobalExceptionHandlers.handler(req,res,e);
                    }
                });
            }
        }

    }

    private HttpMethod methodStringToHttpMethod(String method) {
        String toUpperCase = method.toUpperCase();
        return HttpMethod.valueOf(toUpperCase);
    }
}
